require("common")
require("renderer")

form = {
	new = function(name, suffix)
		assert((type(name) == "string") or (name == nil), "name must be a string or nil")
		local self = {}
		if name == nil then name = "form" end
		if suffix == nil then suffix = "xhtml" end
		self.path = string.format("%s/%s.%s", common.getConfig("path.user.tmpdir"), name, suffix)
		self.r = renderer.new(self.path)
		setmetatable(self, { __index = form })
		self.fontFamily = common.getConfig("screen.font.family")
		self.fontSize = common.getConfig("screen.font.size")
		self.border = 5
		self.border2 = 14
		self.controlGap = 39
		return self
	end,
	
	getCommonCss = function(self)
		return {
			body = {
				margin = "0px",
				padding = "0px",
				["font-family"] = self.fontFamily,
				["font-size"] = self.fontSize .. "px",
				color = "#ffffff"
			},
			[".clickable"] = {
				["font-weight"] = "bold",
				cursor = "pointer"
			},
			[".smallfont"] = {
				["font-size"] = "50%"
			},
		}
	end,
	
	close = function(self)
		self.r:close()
	end,
	
	beginForm = function(self, width, height, background, handler)
		local border = self.border .. "px solid #ffffff"
		local borderLight = "1px solid #ffffff"
		local borderDark= "1px solid #aaaaaa"
		self.r:xmlHeader("UTF-8")
		self.r:htmlBegin()
		self.r:beginl("head")
		self.r:beginl("style")
		self.r:cssSheet(self:getCommonCss())
		self.r:cssSheet({
			body = {
				height = height .. "px",
				background = string.format("url(%s) left top no-repeat", self:getImageUrl(background)),
			},
			[".html"] = {},
			[".text"] = {
				position = "absolute",
				cursor = "default"
			},
			[".label"] = {
				position = "absolute",
				cursor = "default"
			},
			[".centered"] = {
				["text-align"] = "center"
			},
			[".border"] = {
				stroke = "#ffffff",
				["stroke-width"] = self.border .. "px",
				["stroke-linecap"] = "round",
				["stroke-linejoin"] = "round",
				fill = "none"
			},
			[".fill"] = {
				fill = "#ffffff",
				["fill-opacity"] = "0.5"
			},
			[".anchor"] = {
				color = "#ffffff",
				["text-decoration"] = "none",
				cursor = "default"
			},
			[".list"] = {
				overflow = "auto"
			},
			[".list-item"] = {
				cursor = "default",
				whitespace = "nobreak"
			},
			[".textfield"] = {
				border = "0px none",
				color = "#ffffff",
				background = "none"
			},
			[".textfield:focus"] = {
				border = "1px solid #606060"
			},
			[".frame"] = {
				border = "0px none",
				margin = "0px",
				padding = "0px"
			},
			--[[
			[".border-outer"] = {
				["border-top"] = borderLight,
				["border-right"] = borderDark,
				["border-bottom"] = borderDark,
				["border-left"] = borderLight
			},
			[".border-inner"] = {
				["border-top"] = borderDark,
				["border-right"] = borderLight,
				["border-bottom"] = borderLight,
				["border-left"] = borderDark,
				margin = "3px"
			},
			]]
		})
		self:renderRoundRectCss("border2", 14, "border")
		self:renderRoundRectCss("roundrect", 14, "roundrect")
		if handler then handler("style", self) end
		self.r:endl("style")
		self:beginScript()
		self.r:pe([[
			document.oncontextmenu = function(evt){
				alert("Disabled");
				return false;
			}
			function notify(message){
			    window.status = message;
			}
			function clicked(what){
			    notify("CLICKED " + what);
			}
			function startClock(clock){
			    var setHand = function(which, deg){
			        var hand = clock.ownerDocument.getElementById("clock_" + which);
			        hand.setAttribute("transform", "rotate(" + deg + ")");
			    };
			    var tick = function(){
			        var now = new Date();
			        setHand("second", now.getSeconds() * 360 / 60);
			        setHand("minute", now.getMinutes() * 360 / 60);
			        setHand("hour", (now.getHours() * 360 / 12) + (now.getMinutes() * 360 / 720));
			        window.setTimeout(tick, 1000);
			    };
			    tick();
			}
			function setClass(id, clazz){
				var e = document.getElementById(id);
				e.setAttribute("class", clazz);
			}
			function setText(id, text){
				var e = document.getElementById(id);
				e.innerText = text;
			}
			function getValue(id){
				var e = document.getElementById(id);
				notify("VALUE " + id + ":" + encodeURIComponent(e.value));
			}
			function setValue(id, value){
				var e = document.getElementById(id);
				e.value = decodeURIComponent(value);
			}
			function focus(id){
				var e = document.getElementById(id);
				e.focus();
				e.value = e.value;
			}
			function setLocation(name, url){
				var frame = window.frames[name];
				frame.location.href = url;
			}
		]])
		if handler then handler("script", self) end
		self:endScript()
		self.r:endl("head")
		self.r:beginl("body", { onload = "if(onload != null){ onload(); }" })
	end,
	
	renderRoundRectCss = function(self, cssPrefix, roundSize, imagePrefix)
		local rs = roundSize .. "px"
		self.r:cssSheet({
			["." .. cssPrefix] = {},
			["." .. cssPrefix .. "-lt"] = { width = rs, height = rs, background = string.format("url(%s) left top no-repeat", self:getImageUrl(imagePrefix .. "_lt.png")) },
			["." .. cssPrefix .. "-rt"] = { width = rs, height = rs, background = string.format("url(%s) right top no-repeat", self:getImageUrl(imagePrefix .. "_rt.png")) },
			["." .. cssPrefix .. "-lb"] = { width = rs, height = rs, background = string.format("url(%s) left bottom no-repeat", self:getImageUrl(imagePrefix .. "_lb.png")) },
			["." .. cssPrefix .. "-rb"] = { width = rs, height = rs, background = string.format("url(%s) right bottom no-repeat", self:getImageUrl(imagePrefix .. "_rb.png")) },
			["." .. cssPrefix .. "-l"] = { width = rs, background = string.format("url(%s) left center repeat-y", self:getImageUrl(imagePrefix .. "_l.png")) },
			["." .. cssPrefix .. "-r"] = { width = rs, background = string.format("url(%s) right center repeat-y", self:getImageUrl(imagePrefix .. "_r.png")) },
			["." .. cssPrefix .. "-t"] = { height = rs, background = string.format("url(%s) center top repeat-x", self:getImageUrl(imagePrefix .. "_t.png")) },
			["." .. cssPrefix .. "-b"] = { height = rs, background = string.format("url(%s) center bottom repeat-x", self:getImageUrl(imagePrefix .. "_b.png")) },
			["." .. cssPrefix .. "-inner"] = { background = string.format("url(%s) center center repeat", self:getImageUrl(imagePrefix .. "_inner.png")) },
		})
	end,
	
	getImageUrl = function(self, filename)
		return string.format("file://%s/%s", common.absolutePath(common.getConfig("path.imagedir")), filename)
	end,
	
	renderImagePreload = function(self, id, path)
		self.r:pel(string.format("var i%d = new Image(); i%d.src = '%s';", id, id, self:getImageUrl(path)))
	end,
	
	beginScript = function(self, src)
		self.r:beginl("script", { type = "text/javascript", src = src })
	end,
	
	endScript = function(self)
		self.r:endl("script")
	end,
	
	script = function(self, src, code)
		self:beginScript(src)
		if code ~= nil then self.r:pl(code) end
		self:endScript()
	end,
	
	beginFormHtml = function(self)
		self.r:htmlDivBegin("html")
	end,
	
	endFormHtml = function(self)
		self.r:htmlDivEnd("html")
	end,
	
	renderFormLabel = function(self, text, event, x, y, width, id, centered)
		if centered == nil then centered = true end
		local onmousedown
		if event then
			onmousedown = string.format("clicked('%s');", event)
		end
		local css = "label"
		if centered then css = css .. " centered" end
		self.r:htmlDiv(css, {
			id = id,
			onmousedown = onmousedown,
			style = { left = x .. "px", top = y .. "px", width = width .. "px" }
		}, text)
	end,
	
	beginList = function(self, x, y, width, height)
		width = width - (2 * self.border2)
		height = height - (2 * self.border2)
		local top, right, bottom, left = self:getXY(x, y)
		self:beginBorder({
			position = "absolute",
			left = left,
			top = top,
			right = right,
			bottom = bottom
		})
		self.r:htmlDivBegin("list", { style = {
			width = width .. "px",
			height = height .. "px"
		}})
		self.r:beginl("table")
	end,
	
	endList = function(self)
		self.r:_end("table")
		self.r:htmlDivEnd("list")
		self:endBorder()
	end,
	
	renderListItem = function(self, name, notify, indent, id)
		local onclick
		local class = "list-item smallfont"
		if notify then
			onclick = string.format("clicked('%s');", notify)
			class = class .. " clickable"
		end
		self.r:begin("tr")
		self.r:begin("td", { id = id, class = class, style = { ["padding-left"] = (0.5 + indent) .. "em" }, onmousedown = onclick })
		self.r:pe(name)
		self.r:_end("td")
		self.r:endl("tr")
	end,
	
	beginFormSvg = function(self)
		self.r:svgBegin()
	end,
	
	endFormSvg = function(self)
		self.r:svgEnd()
	end,
	
	endForm = function(self)
		self.r:endl("body")
		self.r:htmlEnd()
	end,
	
	renderFormClock = function(self, radius, x, y)
		local radius2 = radius * 55 / 100
		local radius3 = radius * 85 / 100
		self.r:beginl("g", { id = "clock", transform = "translate(" .. x .. ", " .. y .. ")", onload = "startClock(this)" })
		self.r:elementl("path", {
			d = string.format("M 0 %g A %g %g 0 1 1 0.001 %g z M 0 %g A %g %g 0 1 0 0.001 %g z ", radius, radius, radius, radius, -radius2, radius2, radius2, -radius2),
			class = "border fill"
		})
		self.r:elementl("line", { id = "clock_hour", x1 = 0, y1 = 0, x2 = 0, y2 = -radius2, class = "border" })
		self.r:elementl("line", { id = "clock_minute", x1 = 0, y1 = -radius2, x2 = 0, y2 = -radius3, class = "border" })
		self.r:elementl("line", { id = "clock_second", x1 = 0, y1 = -radius3, x2 = 0, y2 = -radius, class = "border" })
		self.r:endl("g")
	end,
	
	renderFormSvg = function(self, name, x, y, scale, event)
		local path = string.format("%s/%s.svg", common.getConfig("path.svgdir"), name)
		local file = io.open(path, "r")
		if file == nil then
			log("form", "Error: cannot open svg file `%s'", path)
			return
		end
		local onclick = nil
		if event ~= nil then onclick = string.format("clicked('%s');", event) end
		self.r:beginl("g", { transform = string.format("translate(%g, %g) scale(%g)", x, y, scale), onmousedown = onclick })
		for line in file:lines() do
			self.r:pl(line)
		end
		self.r:endl("g")
		file:close()
	end,
	
	getControlTitle = function(self, name)
		assert(type(name) == "string")
		return common.getResource("control." .. name:gsub("_", "."))
	end,
	
	getControlWidth = function(self, name)
		local title = self:getControlTitle(name)
		local avgCharWidth = common.getConfig("controls.avgCharWidth")
		return (title:utf8len() * avgCharWidth) + (2 * self.controlGap)
	end,
	
	beginControls = function(self, width)
		-- self:beginControls1()
		self:beginControls2(width)
	end,
	
	endControls = function(self)
		-- self:endControls1()
		self:endControls2()
	end,
	
	renderControl = function(self, name, width, left)
		-- self:renderControl1(name)
		self:renderControl2(name, width, left)
	end,
	
	beginControls1 = function(self)
		self.r:beginl("table", { class = "control-table", cellpadding = 0, cellspacing = 0 })
		self.r:beginl("tr")
	end,
	
	endControls1 = function(self)
		self.r:endl("tr")
		self.r:endl("table")
	end,
	
	renderControl1 = function(self, name)
		local title = self:getControlTitle(name)
		self.r:beginl("td", {
			id = "control_" .. name,
			class = "control-item",
			align = "center", valign = "center",
			width = self:getControlWidth(name) .. "px",
			onmousedown = string.format("clicked('%s');", name)
		})
		self.r:htmlSpan(nil, nil, title)
		self.r:endl("td")
	end,
	
	beginControls2 = function(self, width)
		self.r:htmlDivBegin("controls", { style = { width = width .. "px" } })
		self.r:htmlDivBegin("controls-m")
		self.r:htmlDivBegin("controls-l")
		self.r:htmlDivBegin("controls-r")
		self.r:htmlDivBegin("controls-inner")
	end,
	
	endControls2 = function(self)
		self.r:htmlDivEnd("controls-inner")
		self.r:htmlDivEnd("controls-r")
		self.r:htmlDivEnd("controls-l")
		self.r:htmlDivEnd("controls-m")
		self.r:htmlDivEnd("controls")
	end,
	
	renderControl2 = function(self, name, width, left)
		self.r:htmlDivBegin("control", {
			id = "control_" .. name,
			style = { width = width .. "px", left = left .. "px" },
			onmousedown = string.format("clicked('%s');", name)
		})
		self.r:htmlDivBegin("control-l")
		self.r:htmlDivBegin("control-r")
		self.r:htmlDivBegin("control-m")
		self.r:htmlDivBegin("control-inner")
		self.r:htmlDivBegin("control-inner-2")
		self.r:pel(self:getControlTitle(name))
		self.r:htmlDivEnd("control-inner-2")
		self.r:htmlDivEnd("control-inner")
		self.r:htmlDivEnd("control-m")
		self.r:htmlDivEnd("control-r")
		self.r:htmlDivEnd("control-l")
		self.r:htmlDivEnd("control")
	end,
	
	renderControlShift = function(self, minimize, left)
		local css
		if minimize then css = "control-minimize" else css = "control-maximize" end
		self.r:htmlDiv(css, {
			id = "control_shift",
			onmousedown = "clicked('CONTROL-SHIFT');",
			style = { left = left .. "px" }
		})
	end,
	
	getXY = function(self, x, y)
		local top, right, bottom, left
		if x < 0 then
			right = -x .. "px"
		else
			left = x .. "px"
		end
		if y < 0 then
			bottom = -y .. "px"
		else
			top = y .. "px"
		end
		return top, right, bottom, left
	end,
	
	renderText = function(self, name, x, y, width, height, text, multiline)
		width = width - (2 * self.border2)
		if height ~= nil then height = height - (2 * self.border2) end
		local top, right, bottom, left = self:getXY(x, y)
		self:beginBorder({
			position = "absolute",
			left = left,
			top = top,
			right = right,
			bottom = bottom
		
		})
		if multiline then
			self.r:beginl("textarea", {
				id = name,
				class = "textfield smallfont",
				style = {
					display = "block",
					width = width .. "px",
					height = height .. "px"
				}
			})
			if text ~= nil then self.r:pe(text) end
			self.r:endl("textarea")
		else
			self.r:emptyl("input", {
				id = name,
				["type"] = "text",
				class = "textfield",
				value = text,
				style = {
					display = "block",
					width = width .. "px"
				}
			})
		end
		self:endBorder()
	end,
	
	renderFrame = function(self, x, y, width, height, name, url)
		width = width - (2 * self.border2)
		height = height - (2 * self.border2)
		local top, right, bottom, left = self:getXY(x, y)
		self:beginBorder({
			position = "absolute",
			left = left,
			top = top,
			right = right,
			bottom = bottom
		})
		self.r:beginl("iframe", {
			name = name,
			src = url,
			class = "frame",
			style = {
				width = width .. "px",
				height = height .. "px"
			}
		})
		self.r:endl("iframe")
		self:endBorder()
	end,
	
	beginBorder = function(self, style)
		-- self:beginBorder1(style)
		self:beginBorder2(style)
	end,
	
	endBorder = function(self)
		-- self:endBorder1()
		self:endBorder2()
	end,
	
	beginBorder1 = function(self, style)
		self.r:htmlDivBegin("border-outer", { style = style })
		self.r:htmlDivBegin("border-inner")
	end,
	
	endBorder1 = function(self)
		self.r:htmlDivEnd("border-inner")
		self.r:htmlDivEnd("border-outer")
	end,
	
	beginBorder2 = function(self, style)
		self:beginRoundRect("border2", style)
	end,
	
	endBorder2 = function(self)
		self:endRoundRect("border2")
	end,
	
	beginRoundRect = function(self, prefix, style)
		self.r:beginl("table", {
			class = prefix,
			style = style,
			cellpadding = 0,
			cellspacing = 0
		})
		self.r:beginl("tr")
		self.r:elementl("td", { class = prefix .. "-lt" }, "")
		self.r:elementl("td", { class = prefix .. "-t" }, "")
		self.r:elementl("td", { class = prefix .. "-rt" }, "")
		self.r:endl("tr")
		self.r:beginl("tr")
		self.r:elementl("td", { class = prefix .. "-l" }, "")
		self.r:beginl("td", { class = prefix .. "-inner" })
	end,
	
	endRoundRect = function(self, prefix)
		self.r:endl("td")
		self.r:elementl("td", { class = prefix .. "-r" }, "")
		self.r:endl("tr")
		self.r:beginl("tr")
		self.r:elementl("td", { class = prefix .. "-lb" }, "")
		self.r:elementl("td", { class = prefix .. "-b" }, "")
		self.r:elementl("td", { class = prefix .. "-rb" }, "")
		self.r:endl("tr")
		self.r:endl("table")
	end,
	
	getClockSize = function(self)
		local clockRadius = common.getConfig("screen.clock.radius")
		local clockGap = common.getConfig("screen.clock.gap")
		return (clockRadius + clockGap) * 2
	end,
	
	getControlSize = function(self)
		return 100
	end
}


